/*
 * Copyright (C) 2010-2011 Comcast Cable.  All Rights Reserved.
 */
package com.hercules.android.receiver.painting.resources;

import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.hercules.android.receiver.LogUtil;
import com.hercules.android.receiver.handlers.events.EventRaisingException;
import com.hercules.android.receiver.model.commands.XRECommand;
import com.hercules.android.receiver.model.commands.XRESetCommand;
import com.hercules.android.receiver.model.events.XREHTMLEvent;
import com.hercules.android.receiver.model.objects.XREHTMLView;
import com.hercules.android.receiver.painting.PaintersUtil;
import com.hercules.android.receiver.painting.views.XRELayoutParams;

/**
 * Painter for {@link XREHTMLView} resource. It will use {@link WebView} to display html url.
 * <p>
 * AndroidAssembly3 this class was added in Android Assembly 3
 * <p>
 * <b>Thread safety:</b> Not thread safe, because base class is not thread safe
 *
 * @author TCSASSEMBLER
 * @version 1.0
 */
public class XREHTMLViewPainter extends BaseXREResourcePainter implements OnTouchListener {
    /**
     * Represents {@link WebView} that will be used to display url content.
     * <p>
     * It will be initialized in init() method and used in other method util it will be destroyed in finish() method.
     */
    private WebView webView;

    /**
     * Constructor for class {@link XREHTMLViewPainter}.
     *
     * @param xreResource the {@link XREHTMLView}
     */
    public XREHTMLViewPainter(XREHTMLView xreResource) {
        super(xreResource);
    }

    /**
     * Performs initialize actions.
     *
     * @throws IllegalStateException if required fields are not set
     */
    @Override
    public void init() {
        final String methodName = "init";
        LogUtil.enter(getLogger(), this, methodName);

        try {
            PaintersUtil.checkState(getReceiver(), "receiver");
            PaintersUtil.checkState(getXREView(), "xreView");
            PaintersUtil.checkState(getAndroidView(), "androidView");

            // add WebView to UI view
            getAndroidView().runOnUI(new Runnable() {
                public void run() {
                    synchronized (XREHTMLViewPainter.this) {
                        // setup the web view
                        webView = new WebView(getAndroidView().getContext());
                    }

                    // configure web settings
                    webView.getSettings().setJavaScriptEnabled(true);
                    webView.getSettings().setBuiltInZoomControls(true);

                    // add view
                    webView.setLayoutParams(new XRELayoutParams(getXREView()));
                    getAndroidView().addView(webView);
                    getAndroidView().setClipChildren(true);

                    // set handler for onScroll event
                    webView.setOnTouchListener(XREHTMLViewPainter.this);

                    // add onHTMLClickedEvent listener
                    webView.setWebViewClient(new WebViewClient() {
                        /**
                         * Overrides url loading. It will also raise corresponding event.
                         *
                         * @param view the current WebView
                         * @param url the URL that should be loaded
                         * @return true, that indicates that view has handled URL loading
                         */
                        @Override
                        public boolean shouldOverrideUrlLoading(WebView view, String url) {
                            view.loadUrl(url);

                            // create event
                            XREHTMLEvent event = new XREHTMLEvent();
                            event.setName(XREHTMLEvent.ON_HTML_LINK_CLICKED_EVENT_NAME);
                            event.setSource(getHTMLView().getId());
                            event.setValue(url);

                            try {
                                // raise event
                                getEventRaiser().raiseEvent(event, getReceiver(), true);
                            } catch (EventRaisingException e) {
                                LogUtil.error(getLogger(), XREHTMLViewPainter.this, methodName, e);
                            }
                            return true;
                        }
                    });

                    // load data and invalidate
                    webView.loadUrl(getHTMLView().getUrl());
                    getAndroidView().invalidate();
                }
            });

        } catch (IllegalStateException e) {
            throw LogUtil.error(getLogger(), this, methodName, e);
        }

        LogUtil.exit(getLogger(), this, methodName);
    }

    /**
     * Performs clean up.
     *
     * @throws IllegalStateException if required fields are not set
     */
    @Override
    public void finish() {
        String methodName = "finish";
        LogUtil.enter(getLogger(), this, methodName);

        try {
            PaintersUtil.checkState(getReceiver(), "receiver");
            synchronized (this) {
                PaintersUtil.checkState(webView, "webView");
            }

            getAndroidView().runOnUI(new Runnable() {
                public void run() {
                    // remove view
                    getAndroidView().removeView(webView);

                    // release the web view
                    webView.destroy();
                }
            });
        } catch (IllegalStateException e) {
            throw LogUtil.error(getLogger(), this, methodName, e);
        }

        LogUtil.exit(getLogger(), this, methodName);
    }

    /**
     * Handle {@link XRECommand}.
     *
     * @param command the command to handle
     */
    @Override
    public void handleCommand(XRECommand command) {
        final String methodName = "handleCommand";
        LogUtil.enter(getLogger(), this, methodName);

        synchronized (this) {
            if (webView != null) {
                if (command instanceof XRESetCommand) {
                    XRESetCommand setCommand = (XRESetCommand) command;

                    // apply layout if dimensions have changed
                    if (setCommand.getProps().containsKey("dimensions")) {
                        getAndroidView().runOnUI(new Runnable() {
                            public void run() {
                                webView.setLayoutParams(new XRELayoutParams(getXREView()));
                            }
                        });
                    }
                }
            }
        }
        LogUtil.exit(getLogger(), this, methodName);
    }

    /**
     * Touch event listener. Used to raise onScroll events.
     *
     * @param v the current view
     * @param motionEvent the {@link MotionEvent}
     * @return always false
     */
    public boolean onTouch(View v, MotionEvent motionEvent) {
        if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
            // create event
            XREHTMLEvent event = new XREHTMLEvent();
            event.setName(XREHTMLEvent.ON_SCROLL_EVENT_NAME);
            event.setSource(getHTMLView().getId());

            try {
                // raise event
                getEventRaiser().raiseEvent(event, getReceiver(), true);
            } catch (EventRaisingException e) {
                LogUtil.error(getLogger(), this, "onTouch", e);
            }
        }
        return false;
    }

    /**
     * Gets {@link XREHTMLView}.
     *
     * @return the corresponding {@link XREHTMLView}
     */
    private XREHTMLView getHTMLView() {
        return (XREHTMLView) getXREResource();
    }
}
